package com.test.handler;

import com.test.exception.XmlBeanDefinitionStoreException;
import com.test.registry.BeanDefinitionRegistry;
import org.dom4j.Element;

import java.util.HashMap;
import java.util.Map;

/**
 * 抽象命名空间处理器类，实现了命名空间处理器接口
 * 该类负责管理元素解析器和属性装饰器的注册，并提供解析元素和装饰属性的方法
 */
public abstract class AbstractNamespaceHandler implements NamespaceHandler{

    // 存储元素名称与元素解析器的映射
    private final Map<String, ElementParser> elementParsers = new HashMap<>();

    // 存储属性名称与属性装饰器的映射
    private final Map<String, AttributeDecorator> attributeDecorators = new HashMap<>();

    /**
     * 注册元素解析器
     *
     * @param elementName 元素名称
     * @param elementParser 元素解析器
     */
    protected void registerElementParser(String elementName, ElementParser elementParser) {
        elementParsers.put(elementName, elementParser);
    }

    /**
     * 注册属性装饰器
     *
     * @param attributeName 属性名称
     * @param attributeDecorator 属性装饰器
     */
    protected void registerAttributeDecorator(String attributeName, AttributeDecorator attributeDecorator) {
        attributeDecorators.put(attributeName, attributeDecorator);
    }

    /**
     * 解析元素根据元素名称查找对应的元素解析器，并委托其解析元素
     *
     * @param element 待解析的元素
     * @param registry Bean定义注册表
     * @throws XmlBeanDefinitionStoreException 如果元素未知且没有对应的解析器
     */
    public void parse(Element element, BeanDefinitionRegistry registry) {
        String localName = element.getName();
        ElementParser elementParser = elementParsers.get(localName);
        if (elementParser != null) {
            elementParser.parse(element, registry);
        }else {
            throw new XmlBeanDefinitionStoreException("未知的元素 [" + localName + "]在命名空间 [" + element.getNamespaceURI() + "]");
        }
    }

    /**
     * 装饰属性根据属性名称查找对应的属性装饰器，并委托其装饰元素
     *
     * @param element 待装饰的元素
     * @param attributeName 属性名称
     * @param registry Bean定义注册表
     * @throws XmlBeanDefinitionStoreException 如果属性未知且没有对应的装饰器
     */
    public void docorate(Element element, String attributeName, BeanDefinitionRegistry registry) {
        AttributeDecorator attributeDecorator = attributeDecorators.get(attributeName);
        if (attributeDecorator != null) {
            attributeDecorator.decorate(element, attributeName, registry);
        }else {
            throw new XmlBeanDefinitionStoreException("未知的属性 [" + attributeName + "]在命名空间 [" + element.getNamespaceURI() + "]");
        }
    }

    /**
     * 元素解析器接口，用于解析特定的元素
     */
    public interface ElementParser {
        void parse(Element element, BeanDefinitionRegistry registry);
    }

    /**
     * 属性装饰器接口，用于装饰特定的属性
     */
    public interface AttributeDecorator {
        void decorate(Element element, String attributeName, BeanDefinitionRegistry registry);
    }
}
